package com.pony.iphone.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pony.iphone.dto.TimeRange;
import com.pony.iphone.entity.Error;
import com.pony.iphone.mapper.ErrorMapper;
import com.pony.iphone.service.ErrorService;
import com.pony.iphone.utils.R;
import com.pony.iphone.utils.AppHttpCodeEnum;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pony.iphone.vo.ErrorItemVO;
import com.pony.iphone.vo.ErrorStatsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author pony
 */
@Slf4j
@Service
public class ErrorServiceImpl extends ServiceImpl<ErrorMapper, Error> implements ErrorService {

    @Autowired
    private ErrorMapper errorMapper;

    /**
     * 批量处理错误信息，添加到数据库
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R countError(List<String> errorNames) {
        try {
            if (CollectionUtils.isEmpty(errorNames)) {
                return R.error(AppHttpCodeEnum.PARAMETER_LACK).message("错误名称列表为空");
            }

            // 去重处理
            List<String> distinctNames = errorNames.stream()
                    .filter(Objects::nonNull)
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    .distinct()
                    .toList();

            // 批量插入新记录
            List<Error> newErrors = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();

            for (String name : distinctNames) {
                Error newError = new Error();
                newError.setName(name);
                newError.setCreateTime(now);
                newError.setUpdateTime(now);
                newErrors.add(newError);
            }

            // 批量保存
            boolean saveResult = this.saveBatch(newErrors);
            if (!saveResult) {
                return R.error(AppHttpCodeEnum.ERROR).message("批量插入失败");
            }

            // 构建响应
            Map<String, Object> processResults = newErrors.stream()
                    .collect(Collectors.toMap(
                            Error::getName,
                            error -> {
                                Map<String, Object> result = new HashMap<>();
                                result.put("processed", true);
                                result.put("errorId", error.getId());
                                result.put("message", "错误已记录");
                                result.put("operation", "insert");
                                result.put("createTime", error.getCreateTime());
                                return result;
                            }
                    ));

            return R.success(AppHttpCodeEnum.SUCCESS)
                    .message(String.format("批量处理完成，共记录%d个错误", distinctNames.size()))
                    .data("totalCount", distinctNames.size())
                    .data("successCount", distinctNames.size())
                    .data("failCount", 0)
                    .data("results", processResults);

        } catch (Exception e) {
            log.error("批量处理错误信息失败: ", e);
            return R.error(AppHttpCodeEnum.ERROR).message("系统处理异常: " + e.getMessage());
        }
    }

    /**
     * 获取错误统计信息
     * @param timeRange
     * @return
     */
    @Override
    public R countInfo(TimeRange timeRange) {
        try {
            if (timeRange == null) {
                return R.error(AppHttpCodeEnum.PARAMETER_LACK).message("时间范围参数不能为空");
            }

            // 根据时间范围构建查询条件
            LocalDateTime startTime = getStartTimeByRange(timeRange);
            LocalDateTime endTime = getEndTimeByRange(timeRange);

            // 查询指定时间范围内的错误记录
            LambdaQueryWrapper<Error> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.between(Error::getCreateTime, startTime, endTime);
            List<Error> rangeErrors = this.list(queryWrapper);



            // 统计各类数据
            ErrorStatsVO statsVO = calculateErrorStats(rangeErrors, timeRange, startTime, endTime);

            return R.success(AppHttpCodeEnum.SUCCESS)
                    .message(String.format("获取%s错误统计成功", getTimeRangeDisplayName(timeRange)))
                    .data("stats", statsVO);

        } catch (Exception e) {
            log.error("获取错误统计失败: ", e);
            return R.error(AppHttpCodeEnum.ERROR).message("获取统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 计算错误统计信息
     */
    private ErrorStatsVO calculateErrorStats(List<Error> errors, TimeRange timeRange,
                                             LocalDateTime startTime, LocalDateTime endTime) {
        ErrorStatsVO statsVO = new ErrorStatsVO();

        // 按错误名称分组，同时获取该错误的最新记录信息
        Map<String, List<Error>> errorsByName = errors.stream()
                .collect(Collectors.groupingBy(Error::getName));

        // 转换为 VO 列表，使用每组中的第一条记录来获取 id、createTime、updateTime
        List<ErrorItemVO> errorItems = errorsByName.entrySet().stream()
                .map(entry -> {
                    String errorName = entry.getKey();
                    List<Error> errorList = entry.getValue();
                    Error firstError = errorList.get(0); // 使用第一条记录获取基础信息

                    ErrorItemVO itemVO = new ErrorItemVO();
                    itemVO.setId(firstError.getId());
                    itemVO.setName(errorName);
                    itemVO.setCount(errorList.size()); // 计数就是该错误出现的次数
                    itemVO.setCreateTime(firstError.getCreateTime().toString());
                    itemVO.setUpdateTime(firstError.getUpdateTime().toString());
                    itemVO.setIsErrorPrefix(errorName != null && errorName.startsWith("error:"));
                    return itemVO;
                })
                .collect(Collectors.toList());

        // 计算以 error: 开头的错误总计数
        long totalErrorPrefixCount = errors.stream()
                .filter(error -> error.getName() != null && error.getName().startsWith("error:"))
                .count();

        // 计算 getGmail 错误的总计数
        long totalGetGmailCount = errors.stream()
                .filter(error -> error.getName() != null && "getGmail".equals(error.getName()))
                .count();

        // 设置统计结果
        statsVO.setErrorList(errorItems);
        statsVO.setTotalErrorPrefixCount((int) totalErrorPrefixCount);
        statsVO.setTotalGetGmailCount((int) totalGetGmailCount);
        statsVO.setTotalErrorTypes(errorsByName.size());
        // 总错误发生次数就是记录数
        statsVO.setTotalErrorOccurrences(errors.size());
        statsVO.setTimeRange(timeRange.name());
        statsVO.setStartTime(startTime.toString());
        statsVO.setEndTime(endTime.toString());

        return statsVO;
    }

    /**
     * 根据时间范围获取开始时间
     */
    private LocalDateTime getStartTimeByRange(TimeRange timeRange) {
        LocalDate today = LocalDate.now();

        switch (timeRange) {
            case TODAY:
                return today.atStartOfDay();
            case YESTERDAY:
                return today.minusDays(1).atStartOfDay();
            case WEEK:
                return today.minusWeeks(1).atStartOfDay();
            case MONTH:
                return today.minusMonths(1).atStartOfDay();
            default:
                return today.atStartOfDay();
        }
    }

    /**
     * 根据时间范围获取结束时间
     */
    private LocalDateTime getEndTimeByRange(TimeRange timeRange) {
        LocalDate today = LocalDate.now();

        switch (timeRange) {
            case TODAY:
                return today.plusDays(1).atStartOfDay();
            case YESTERDAY:
                return today.atStartOfDay(); // 昨天结束时间是今天0点
            case WEEK:
            case MONTH:
                return today.plusDays(1).atStartOfDay();
            default:
                return today.plusDays(1).atStartOfDay();
        }
    }

    /**
     * 获取时间范围的中文显示名称
     */
    private String getTimeRangeDisplayName(TimeRange timeRange) {
        switch (timeRange) {
            case TODAY:
                return "今天";
            case YESTERDAY:
                return "昨天";
            case WEEK:
                return "一周内";
            case MONTH:
                return "一月内";
            default:
                return "今天";
        }
    }
}
